package com.googlecode.astoolkit.utils {
	
	import com.googlecode.astoolkit.modules.content.section.ISection;

	public class Sitemap {
		
		private static var _instance:Sitemap;
		private var _data:XML;
		private var _nodes:Array;

		public function Sitemap(singletonenforcer:SingletonEnforcer){
			if (singletonenforcer == null) {
				throw new Error("Sitemap es un Singleton. Para acceder a una instancia hacedlo mediante Sitemap.getInstance()");
				return ;
			}
			
			_nodes = new Array();
		}
		
		public static function getInstance():Sitemap {
			if (!_instance) {
				_instance = new Sitemap(new SingletonEnforcer());
			}
			return _instance;
		}
		
		//
		public function set data(rawXml:XML):void{
			if (!_data) {
				_data = setIds(rawXml);
				createNodes(_data);
			}
		} 
		
		public static function getNodeById(id:int):INode{
			var node:INode; 
			if(id!=-1){
				node = Sitemap.nodes[id];
			}else{
				node = new NullNode();
			}
			//trace("getNodeById-->" + node);
			return node;
		}
		
		//
		 public static function getNodeByPath(path:String):INode{
			var nodes:Array = Sitemap.nodes;
			for each(var n:INode in nodes){
				if(n.path == path){
					return n;
				}
			}
			return new NullNode();
		} 
		
		//
		public static function getIdByPath(path:String):int{
			return Sitemap.getNodeByPath(path).id;
		} 
		
		//
		public static function getIdsArrayByPath(path:String):Array{
			var arr:Array = new Array();
			loop(Sitemap.getNodeByPath(path));
			function loop(node:INode):void{
				if(node is Node){
					arr.splice(0,0, node.id)
					loop(node.parent);
				}
			}
			return arr;
		} 
		
		// Getter y Setter de _data
		public static function get xml():XML{
		     return Sitemap.getInstance()._data;
		}
		
		// Getter de _nodes
		public static function get nodes():Array{
		     return Sitemap.getInstance()._nodes;
		} 
		
		// Getter de _defaultPath
		public static function get defaultPath():String{
			var path:String = "";
			if(Sitemap.xml.hasOwnProperty("@defaultPath")){
				path = Sitemap.xml.@defaultPath;
			}
		      return path;
		}
		

/*****************************************
 Private Functions
******************************************/


		
		// Inyecta los ids
		 private function setIds(data:XML):XML {
			var id:uint = 0;

			//_data = new XML(data);
			data.@id = id++;
			loop(data);

			function loop(branch:XML):void {
				var l:uint = branch.children().length();
				//trace("l-->" + l);
				for(var i:uint = 0; i < l; i++) {
					var subBranch:XML = branch.children()[i];
					// Solo numero los nodos de tipo section
					if(subBranch.name() == "section"){
						subBranch.@id = id++;
					}
					
					// si la rama tiene hijos lo hago recursivo
					if (subBranch.children().length() > 0) {
						loop(subBranch);
					}
				}
			}
			return data;
		}
		
		
		private function createNodes(data:XML):void {
			addNode(0, new MainNode(data));
			loop(data);
			//trace(data.section[1]);
			//return
			function loop(branch:XML):void {
				for each(var subBranch:XML in branch.section) {
					//trace("subBranch-->" + subBranch);
					addNode(subBranch.@id, new Node(subBranch));
					if (subBranch.children().length() > 0) {
						loop(subBranch);
					}
				}
			}
		}


		private static function addNode(id:int, node:AbstractNode):void {
			Sitemap.getInstance()._nodes[id] = node;
		}
		
		

	}
}

class SingletonEnforcer {}